from abc import ABCMeta, abstractmethod
from typing import List, Optional, cast
from dataclasses import dataclass, MISSING
from .expression import Expression

# PoolUpdate 是一个抽象基类，用于处理表达式池的更新操作
@dataclass
class PoolUpdate(metaclass=ABCMeta):
    @property
    @abstractmethod
    def old_pool(self) -> List[Expression]:  # 旧的表达式池
        ...

    @property
    @abstractmethod
    def new_pool(self) -> List[Expression]:  # 新的表达式池
        ...

    @property
    @abstractmethod
    def old_pool_ic(self) -> Optional[float]:  # 旧池的信息系数（IC）
        ...

    @property
    @abstractmethod
    def new_pool_ic(self) -> float:  # 新池的信息系数（IC）
        ...

    @property
    def ic_increment(self) -> float:
        # 计算IC的增量：新IC减去旧IC（如果旧IC不存在则用0代替）
        return self.new_pool_ic - (self.old_pool_ic or 0.)
    
    @abstractmethod
    def describe(self) -> str:  # 简要描述更新内容
        ...
    
    def describe_verbose(self) -> str:  # 详细描述更新内容，默认返回简要描述
        return self.describe()

    def _describe_ic_diff(self) -> str:
        # 生成IC变化的描述字符串
        return (
            f"{self.old_pool_ic:.4f} -> {self.new_pool_ic:.4f} "
            f"(increment of {self.ic_increment:.4f})"
        )

    def _describe_pool(self, title: str, pool: List[Expression]) -> str:
        # 生成表达式池的格式化字符串描述
        list_exprs = "\n".join([f"  {expr}" for expr in pool])
        return f"{title}\n{list_exprs}"


# 用于类型提示的存根类，定义了基本属性
class _PoolUpdateStub:
    old_pool: List[Expression] = cast(List[Expression], MISSING)
    new_pool: List[Expression] = cast(List[Expression], MISSING)
    old_pool_ic: Optional[float] = cast(Optional[float], MISSING)
    new_pool_ic: float = cast(float, MISSING)


# SetPool类用于完全替换表达式池的情况
@dataclass
class SetPool(_PoolUpdateStub, PoolUpdate):
    old_pool: List[Expression]  # 旧的表达式列表
    new_pool: List[Expression]  # 新的表达式列表
    old_pool_ic: Optional[float]  # 旧池的IC值
    new_pool_ic: float  # 新池的IC值
    
    def describe(self) -> str:
        # 生成简要描述，仅包含新池信息
        pool = self._describe_pool("Alpha pool:", self.new_pool)
        return f"{pool}\nIC of the combination: {self.new_pool_ic:.4f}"
    
    def describe_verbose(self) -> str:
        # 生成详细描述，包含新旧池的对比信息
        if len(self.old_pool) == 0:
            return self.describe()
        old_pool = self._describe_pool("Old alpha pool:", self.old_pool)
        new_pool = self._describe_pool("New alpha pool:", self.new_pool)
        perf = f"IC of the pools: {self._describe_ic_diff()})"
        return f"{old_pool}\n{new_pool}\n{perf}"


# AddRemoveAlphas类用于处理添加和删除表达式的情况
@dataclass
class AddRemoveAlphas(_PoolUpdateStub, PoolUpdate):
    added_exprs: List[Expression]  # 新添加的表达式列表
    removed_idx: List[int]  # 要删除的表达式的索引列表
    old_pool: List[Expression]  # 原始表达式池
    old_pool_ic: float  # 原始池的IC
    new_pool_ic: float  # 更新后的IC

    @property
    def new_pool(self) -> List[Expression]:
        # 计算新的表达式池：保留未删除的表达式，并添加新表达式
        remain = [True] * len(self.old_pool)
        for i in self.removed_idx:
            remain[i] = False
        return [expr for i, expr in enumerate(self.old_pool) if remain[i]] + self.added_exprs

    def describe(self) -> str:
        # 生成添加/删除操作的描述
        def describe_exprs(title: str, exprs: List[Expression]) -> str:
            # 内部辅助函数，用于生成表达式列表的描述
            if len(exprs) == 0:
                return ""
            if len(exprs) == 1:
                return f"{title}: {exprs[0]}\n"
            exprs_str = "\n".join([f"  {expr}" for expr in exprs])
            return f"{title}s:\n{exprs_str}\n"

        added = describe_exprs("Added alpha", self.added_exprs)
        removed = describe_exprs("Removed alpha", [self.old_pool[i] for i in self.removed_idx])
        perf = f"IC of the combination: {self._describe_ic_diff()}"
        return f"{added}{removed}{perf}"
    
    def describe_verbose(self) -> str:
        # 生成详细描述，包含完整的旧池信息
        old = self._describe_pool("Old alpha pool:", self.old_pool)
        return f"{old}\n{self.describe()}"
